﻿// 1.2.4.11. Implement the "Falling Rocks" game in the text console. A small dwarf stays at the bottom of the screen and
// can move left and right (by the arrows keys). A number of rocks of different sizes and forms constantly fall down and
// you need to avoid a crash. Rocks are the symbols ^, @, *, &, +, %, $, #, !, ., ;, - distributed with appropriate density.
// The dwarf is (O). Ensure a constant game speed by Thread.Sleep(150). Implement collision detection and scoring system.

using System;
using System.Threading;
using System.Collections.Generic;

class FallenRocks
{
    static int scoreFieldWidth = 8;
    static int playfieldWidth = 50 - (scoreFieldWidth + 1);
    static int playerPosition = playfieldWidth / 2;

    struct Rock
    {
        public int x;
        public int y;
        public char c;
        public ConsoleColor color;
    }

    static void ConsoleConfiguration()
    {
        Console.WindowHeight = 30;
        Console.WindowWidth = playfieldWidth + scoreFieldWidth;
        Console.BufferHeight = Console.WindowHeight;
        Console.BufferWidth = Console.WindowWidth;
        Console.Title = "FallingRocks";
        Console.BackgroundColor = ConsoleColor.White;
    }

    static void PrintCharAtPosition(int x, int y, char c, ConsoleColor color = ConsoleColor.Gray)
    {
        Console.SetCursorPosition(x, y);
        Console.ForegroundColor = color;
        Console.Write(c);
    }

    static void PrintStringOnPosition(int x, int y, string stringForPrint, ConsoleColor color = ConsoleColor.Gray)
    {
        Console.SetCursorPosition(x, y);
        Console.ForegroundColor = color;
        Console.Write(stringForPrint);
    }

    static void DrawPlayer(int playerPosition, char c, ConsoleColor color)
    {
        PrintCharAtPosition(playerPosition - 1, Console.WindowHeight - 1, '<', ConsoleColor.DarkGray);
        PrintCharAtPosition(playerPosition, Console.WindowHeight - 1, c, color);
        PrintCharAtPosition(playerPosition + 1, Console.WindowHeight - 1, '>', ConsoleColor.DarkGray);
    }

    static void Main()
    {
        double speed = 55;
        double acceleration = 0.5;
        Random chanceGenerator = new Random();
        List<Rock> rocks = new List<Rock>();
        int score = 0;
        char[] rockInitialization = new char[12] { '^', '@', '*', '&', '+', '%', '$', '#', '!', '.', ';', '-' };
        ConsoleConfiguration();

        while (true)
        {
            bool collision = false;

            if (speed > 50)
            {
                speed -= acceleration;
            }

            int chance = chanceGenerator.Next(0, 12);
            Rock newRock2 = new Rock();
            newRock2.color = (ConsoleColor)(chanceGenerator.Next(0, 12));   // there is a bug with BLACK rock thats why the background is white.. xD
            newRock2.x = chanceGenerator.Next(0, playfieldWidth);
            newRock2.y = 0;
            newRock2.c = rockInitialization[chance];
            rocks.Add(newRock2);


            if (Console.KeyAvailable) // interacting with the player
            {
                ConsoleKeyInfo pressedKey = Console.ReadKey(true);
                while (Console.KeyAvailable) // helps for responsive moves of the player
                {
                    Console.ReadKey(true);
                }   
                if ((pressedKey.Key == ConsoleKey.LeftArrow) && (playerPosition >= 2))
                {
                    playerPosition--;
                }

                if ((pressedKey.Key == ConsoleKey.RightArrow) && (playerPosition <= playfieldWidth - 3))
                {
                    playerPosition++;
                }


            }
            List<Rock> newList = new List<Rock>();
            for (int i = 0; i < rocks.Count; i++)
            {
                Rock oldRock = rocks[i];
                Rock newRock = new Rock();
                newRock.x = oldRock.x;
                newRock.y = oldRock.y + 1;
                newRock.c = oldRock.c;
                newRock.color = oldRock.color;
                if (newRock.y < Console.WindowHeight)
                {
                    newList.Add(newRock);

                }
                if (newRock.y == Console.WindowHeight - 1)
                {
                    score++;

                    if (newRock.x == playerPosition - 1 || newRock.x == playerPosition + 1 || newRock.x == playerPosition)
                    {
                        collision = true;
                    }

                }

            }
            rocks = newList;

            Thread.Sleep((int)speed);
            Console.Clear();

            if (collision)
            {
                rocks.Clear();
                DrawPlayer(playerPosition, 'O', ConsoleColor.Red);
                PrintStringOnPosition(Console.WindowWidth - 8, Console.WindowHeight / 2, "" + score, ConsoleColor.Black);
                Console.WriteLine();    // to separate the score from the "Press any key to continue . . . "
                break;
            }
            else
            {
                DrawPlayer(playerPosition, 'O', ConsoleColor.Yellow);
            }

            foreach (Rock rock in rocks)
            {
                PrintCharAtPosition(rock.x, rock.y, rock.c, rock.color);
            }
            
        }
    }
}